/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package auxiliares;

import business.ASIFT;
import business.Panorama;
import business.XML;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.tree.DefaultMutableTreeNode;

/**
 *
 * @author Evangelista
 */
public class TreeStreet2 {

    private ArrayList<Panorama> listaPanoramas = new ArrayList<Panorama>();
    private DefaultMutableTreeNode treeMain = new DefaultMutableTreeNode();
    private Queue fila = new Queue();
    private Panorama winner;
    private Panorama viceWinner;
    private double winnerMathces = Double.MIN_VALUE;
    private double viceWinnerMathces = Double.MIN_VALUE;
    public static double[] MASCARA;
//    private PhotoWinners winners = new PhotoWinners();
//    private Histograma histograma = new Histograma();

    // OO
    public void set_raiz(String raiz) {
        this.treeMain.setUserObject(raiz);
    }

    // Construtor da Árvore
    public void build(int tam) {
        build(this.treeMain, tam);
    }

    public void build(DefaultMutableTreeNode tree, int tam) {
        if (tree != null && tree.getRoot() != null && tam > 0) {
            String xml = Server.getContentOfURL("http://cbk0.google.com/cbk?output=xml&panoid=" + tree.getUserObject());
            ArrayList<String> vizinhos = XML.getVizinhos(xml);
            for (int i = 0; i < vizinhos.size(); i++) {
                if (!pertence(treeMain, vizinhos.get(i))) {
                    tree.add(new DefaultMutableTreeNode(vizinhos.get(i)));
                    build((DefaultMutableTreeNode) tree.getChildAt(tree.getChildCount() - 1), tam - 1);
                }
            }
        }
    }

    private boolean pertence(DefaultMutableTreeNode tree, String pano) {
        if (tree == null) {
            return false;
        }

        String panorama = (String) tree.getUserObject();

        if (!panorama.equals(pano)) {
            for (int i = 0; i < tree.getChildCount(); i++) {
                if (pertence((DefaultMutableTreeNode) tree.getChildAt(i), pano)) {
                    return true;
                }
            }
        } else {
            return true;
        }
        return false;
    }

    // Busca em Largura
    public Panorama init_breadth_search() throws InterruptedException, FileNotFoundException, IOException {
        fila = new Queue();
        fila.enqueue((DefaultMutableTreeNode) treeMain.getRoot());
        criaMascara();
        return breadth_search();
    }

    private Panorama breadth_search() throws InterruptedException, FileNotFoundException, IOException {
        if (!fila.isEmpty()) {
            DefaultMutableTreeNode node = fila.dequeue();

            Panorama panoramaAtual = new Panorama((String) node.getUserObject());
            panoramaAtual.iniciarVariaveis();

            ASIFT.exec_ASIFT_ext(panoramaAtual.get_imagem(), panoramaAtual.get_pano_id());

//            histograma.definirPanorama(panoramaAtual);
            
            double matchesAtual = panoramaAtual.criaHistogramaPanorama();
            
            listaPanoramas.add(panoramaAtual);

//            PlotIntegration.save("Teste", panoramaAtual.getLst_vizinhos(), panoramaAtual.getLat(), 
//                    panoramaAtual.getLng(), panoramaAtual.getHistograma().getGrauComMaisMatches(), false);
            
            if (matchesAtual > winnerMathces) {
                viceWinnerMathces = winnerMathces;
                viceWinner = winner;

                winnerMathces = matchesAtual;
                winner = panoramaAtual;

            } else {
                if (matchesAtual > viceWinnerMathces) {
                    viceWinnerMathces = matchesAtual;
                    viceWinner = panoramaAtual;
                }
            }

            // Enfileira os filhos
            for (int i = 0; i < node.getChildCount(); i++) {
                fila.enqueue((DefaultMutableTreeNode) node.getChildAt(i));
            }

            return breadth_search();
        } else {
            return this.winner;
        }
    }
    
        public void criaMascara() {
        double[] pesosHistograma = {-2, -1, 0, +1, +2};
        MASCARA = new double[pesosHistograma.length];
        double soma = 0.0;
        for (int i = 0; i < pesosHistograma.length; i++) {
            pesosHistograma[i] = (Math.exp(-(Math.pow(pesosHistograma[i], 2) / 2.0))) / Math.sqrt(2 * Math.PI);
            soma = soma + pesosHistograma[i];
        }

        for (int i = 0; i < pesosHistograma.length; i++) {
            MASCARA[i] = pesosHistograma[i] / soma;
        }
    }

    public Panorama getWinner() {
        return winner;
    }

    public Panorama getViceWinner() {
        return viceWinner;
    }

//    public int getWinnerMathces() {
//        return winnerMathces;
//    }
//
//    public void setWinnerMathces(int winnerMathces) {
//        this.winnerMathces = winnerMathces;
//    }
//
//    public int getViceWinnerMathces() {
//        return viceWinnerMathces;
//    }
//
//    public void setViceWinnerMathces(int viceWinnerMathces) {
//        this.viceWinnerMathces = viceWinnerMathces;
//    }

    private class Queue {

        private ArrayList<DefaultMutableTreeNode> lista = new ArrayList<DefaultMutableTreeNode>();

        public void enqueue(DefaultMutableTreeNode tree) {
            lista.add(tree);
        }

        public DefaultMutableTreeNode dequeue() {
            if (!this.isEmpty()) {
                DefaultMutableTreeNode nova = lista.get(0);
                lista.remove(0);
                return nova;
            }
            return null;
        }

        public boolean isEmpty() {
            return lista.isEmpty();
        }

        public int getSize() {
            return lista.size();
        }
    }

    public ArrayList<Panorama> getListaPanoramas() {
        return listaPanoramas;
    }

    public void setListaPanoramas(ArrayList<Panorama> listaPanoramas) {
        this.listaPanoramas = listaPanoramas;
    }
    
    
}
